package cn.cucc.utils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.Id;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaDelete;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.CriteriaUpdate;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import cn.cucc.bean.CreateTime;
import cn.cucc.bean.InitValue;
import cn.cucc.bean.PageReq;
import cn.cucc.bean.PageResp;
import cn.cucc.bean.Update;
import cn.cucc.bean.UpdateTime;
import cn.cucc.reflection.ReflectionUtil;
import cn.cucc.reflection.SerializableFunction;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;

/**
 * sql操作器
 *
 */
@Service
public class JpaHelper {
	Logger logger = LoggerFactory.getLogger(this.getClass());

	@Autowired
	EntityManager entityManager;
	@Autowired
	JdbcTemplate jdbcTemplate;

	

	/**
	 * 获取主键
	 * 
	 * @param clazz
	 * @return
	 */
	private String getPrimalKey(Class clazz) {

		Field[] fields = ReflectUtil.getFields(clazz);

		for (Field field : fields) {
			if (field.isAnnotationPresent(Id.class)) {
				return field.getName();
			}
		}

		return null;
	}

	/**
	 * 获取主键值
	 * 
	 * @param clazz
	 * @return
	 */
	private String getPrimalValue(Object object) {
		String key = getPrimalKey(object.getClass());

		if (StrUtil.isNotEmpty(key)) {
			Object obj = ReflectUtil.getFieldValue(object, key);
			return obj != null ? obj.toString() : null;
		}
		return null;
	}
	
	/**
	 * 累加某一个字段的数量,原子操作
	 * 
	 * @param object
	 */
	@Transactional
	public <T, R> void addCountById(String id, SerializableFunction<T, R> property, Long count, Class<?> clazz) {
		addCountById(id, ReflectionUtil.getFieldName(property), count, clazz);
	}
	
	/**
	 * 累加某一个字段的数量,原子操作
	 * 
	 * @param object
	 */
	@Transactional
	public void addCountById(String id, String property, Long count, Class<?> clazz) {
		String sql = "UPDATE `" + StrUtil.toUnderlineCase(clazz.getSimpleName()) + "` SET `" + StrUtil.toUnderlineCase(property) + "` = `" + StrUtil.toUnderlineCase(property)
				+ "` + ? WHERE `id` =  ?";
		Object[] params = new Object[] { count, id };
		logger.info("JdbcTemplate: " + sql);
		jdbcTemplate.update(sql.replace("`", "\""), params);
	}

	/**
	 * 插入或更新
	 * 
	 * @param object 对象 @throws
	 */
	@Transactional
	public String insertOrUpdate(Object object) {
		Long time = System.currentTimeMillis();
		String id = getPrimalValue(object);
		if (StrUtil.isEmpty(id)) {
			// 插入
			// 设置插入时间
			setCreateTime(object, time);
			// 设置更新时间
			setUpdateTime(object, time);
			// 设置默认值
			setDefaultVaule(object);
			// 设置id
			ReflectUtil.setFieldValue(object, getPrimalKey(object.getClass()), SnowFlakeUtils.nextId());
			// 插入
			entityManager.persist(object);
		} else {
			// 更新
			updateById(object);
		}

		// 返回id
		return getPrimalValue(object);
	}

	/**
	 * 插入
	 * 
	 * @param object 对象
	 */
	@Transactional
	public String insert(Object object) {
		// 去除主键id
		ReflectUtil.setFieldValue(object, getPrimalKey(object.getClass()), null);

		// 插入数据库
		insertOrUpdate(object);

		// 返回id
		return getPrimalValue(object);
	}

	/**
	 * 批量插入
	 * 
	 * @param <T>
	 * 
	 * @param object 对象
	 */
	@Transactional
	public <T> void insertAll(Collection<T> list) {
		for (T obj : list) {
			insert(obj);
		}
	}

	/**
	 * 根据id更新
	 * 
	 * @param object 对象
	 */
	@Transactional
	public void updateById(Object object) {
		if (StrUtil.isEmpty(getPrimalValue(object))) {
			return;
		}
		// 设置更新时间
		setUpdateTime(object, System.currentTimeMillis());

		CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
		CriteriaUpdate criteriaUpdate = criteriaBuilder.createCriteriaUpdate(object.getClass());
		Root root = criteriaUpdate.from(object.getClass());
		
		Field[] fields = ReflectUtil.getFields(object.getClass());
		for (Field field : fields) {
			if (!field.getName().equals(getPrimalKey(object.getClass())) && ReflectUtil.getFieldValue(object, field) != null) {
				criteriaUpdate.set(field.getName(), ReflectUtil.getFieldValue(object, field));
			}
		}
		
		criteriaUpdate.where(new ConditionAndWrapper().eq(getPrimalKey(object.getClass()), getPrimalValue(object)).toPredicates(criteriaBuilder, root));
		entityManager.createQuery(criteriaUpdate).executeUpdate();

	}


	/**
	 * 根据id更新全部字段
	 * 
	 * @param object 对象
	 */
	@Transactional
	public void updateAllColumnById(Object object) {
		if (StrUtil.isEmpty(getPrimalValue(object))) {
			return;
		}
		setUpdateTime(object, System.currentTimeMillis());

		CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
		CriteriaUpdate criteriaUpdate = criteriaBuilder.createCriteriaUpdate(object.getClass());
		Root root = criteriaUpdate.from(object.getClass());
		
		Field[] fields = ReflectUtil.getFields(object.getClass());
		for (Field field : fields) {
			if (!field.getName().equals(getPrimalKey(object.getClass()))) {
				criteriaUpdate.set(field.getName(), ReflectUtil.getFieldValue(object, field));
			}
		}
		
		criteriaUpdate.where(new ConditionAndWrapper().eq(getPrimalKey(object.getClass()), getPrimalValue(object)).toPredicates(criteriaBuilder, root));
		entityManager.createQuery(criteriaUpdate).executeUpdate();

	}
	
	
	/**
	 * 条件更新
	 * 
	 * @param conditionAndWrapper
	 * @param update
	 * @param clazz
	 */
	@Transactional
	public void updateByQuery(ConditionWrapper conditionWrapper, Update update, Class<?> clazz) {
		if (update == null || update.getSets().size() == 0) {
			return;
		}

		CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
		CriteriaUpdate criteriaUpdate = criteriaBuilder.createCriteriaUpdate(clazz);
		Root root = criteriaUpdate.from(clazz);

		for (Entry<String, Object> entry : update.getSets().entrySet()) {
			if (entry.getKey() != null && entry.getValue() != null) {
				criteriaUpdate.set(entry.getKey(), entry.getValue());
			}
		}

		criteriaUpdate.where(conditionWrapper.toPredicates(criteriaBuilder, root));

		entityManager.createQuery(criteriaUpdate).executeUpdate();

	}

	

	/**
	 * 根据id删除
	 * 
	 * @param id    对象
	 * @param clazz 类
	 */
	@Transactional
	public void deleteById(String id, Class<?> clazz) {
		if (StrUtil.isEmpty(id)) {
			return;
		}

		deleteByQuery(new ConditionAndWrapper().eq(getPrimalKey(clazz), id), clazz);
	}

	/**
	 * 根据id删除
	 * 
	 * @param id    对象
	 * @param clazz 类
	 */
	@Transactional
	public void deleteByIds(Collection<String> ids, Class<?> clazz) {
		if (ids == null || ids.size() == 0) {
			return;
		}
		deleteByQuery(new ConditionAndWrapper().in(getPrimalKey(clazz), ids), clazz);
	}

	/**
	 * 根据id删除
	 * 
	 * @param id    对象
	 * @param clazz 类
	 */
	@Transactional
	public void deleteByIds(String[] ids, Class<?> clazz) {  
		deleteByQuery(new ConditionAndWrapper().in(getPrimalKey(clazz), ids), clazz);
	}

	/**
	 * 根据条件删除
	 * 
	 * @param query 查询
	 * @param clazz 类
	 */
	@Transactional
	public void deleteByQuery(ConditionWrapper conditionWrapper, Class<?> clazz) {

		CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
		CriteriaDelete criteriaDelete = criteriaBuilder.createCriteriaDelete(clazz);
		Root root = criteriaDelete.from(clazz);

		criteriaDelete.where(conditionWrapper.toPredicates(criteriaBuilder, root));

		entityManager.createQuery(criteriaDelete).executeUpdate();
	}

	/**
	 * 设置默认值
	 * 
	 * @param object 对象
	 */
	private void setDefaultVaule(Object object) {
		Field[] fields = ReflectUtil.getFields(object.getClass());
		for (Field field : fields) {
			// 获取注解
			if (field.isAnnotationPresent(InitValue.class)) {
				InitValue defaultValue = field.getAnnotation(InitValue.class);

				String value = defaultValue.value();

				if (ReflectUtil.getFieldValue(object, field) == null) {
					// 获取字段类型
					Class<?> type = field.getType();
					if (type.equals(String.class)) {
						ReflectUtil.setFieldValue(object, field, value);
					}
					if (type.equals(Short.class)) {
						ReflectUtil.setFieldValue(object, field, Short.parseShort(value));
					}
					if (type.equals(Integer.class)) {
						ReflectUtil.setFieldValue(object, field, Integer.parseInt(value));
					}
					if (type.equals(Long.class)) {
						ReflectUtil.setFieldValue(object, field, Long.parseLong(value));
					}
					if (type.equals(Float.class)) {
						ReflectUtil.setFieldValue(object, field, Float.parseFloat(value));
					}
					if (type.equals(Double.class)) {
						ReflectUtil.setFieldValue(object, field, Double.parseDouble(value));
					}
					if (type.equals(Boolean.class)) {
						ReflectUtil.setFieldValue(object, field, Boolean.parseBoolean(value));
					}
				}
			}
		}
	}

	/**
	 * 设置更新时间
	 * 
	 * @param object 对象
	 */
	private void setUpdateTime(Object object, Long time) {
		Field[] fields = ReflectUtil.getFields(object.getClass());
		for (Field field : fields) {
			// 获取注解
			if (field.isAnnotationPresent(UpdateTime.class) && field.getType().equals(Long.class)) {
				ReflectUtil.setFieldValue(object, field, time);
			}
		}
	}

	/**
	 * 设置创建时间
	 * 
	 * @param object 对象
	 */
	private void setCreateTime(Object object, Long time) {
		Field[] fields = ReflectUtil.getFields(object.getClass());
		for (Field field : fields) {
			// 获取注解
			if (field.isAnnotationPresent(CreateTime.class) && field.getType().equals(Long.class)) {
				ReflectUtil.setFieldValue(object, field, time);
			}
		}
	}

	/**
	 * 按查询条件获取Page
	 * 
	 * @param query 查询
	 * @param page  分页
	 * @param clazz 类
	 * @return Page 分页
	 */
	public <T> PageResp<T> findPageByQuery(ConditionWrapper conditionWrapper, Sort sort, PageReq pageReq, Class<T> clazz) {
		SimpleJpaRepository simpleJpaRepository = new SimpleJpaRepository(clazz, entityManager);
		Specification specification = new Specification() {
			@Override
			public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {
				if (conditionWrapper != null && conditionWrapper.notEmpty()) {
					Predicate predicate = conditionWrapper.toPredicates(criteriaBuilder, root);
					query.where(predicate);
				}

				if (sort != null && !sort.isEmpty()) {
					query.orderBy(sort.toList());
				}

				return query.getGroupRestriction();
			}
		};

		PageImpl jpaPage = (PageImpl) simpleJpaRepository.findAll(specification, PageRequest.of(pageReq.getCurrent() - 1, pageReq.getLimit()));

		PageResp pageResp = new PageResp<>();
		pageResp.setCurrent(pageReq.getCurrent());
		pageResp.setLimit(pageReq.getLimit());
		pageResp.setCount(jpaPage.getTotalElements());
		pageResp.setRecords(jpaPage.getContent());

		return pageResp;
	}

	/**
	 * 按查询条件获取Page
	 * 
	 * @param query 查询
	 * @param page  分页
	 * @param clazz 类
	 * @return Page 分页
	 */
	public PageResp<?> findPageByQuery(Sort sort, PageReq pageReq, Class<?> clazz) {
		return findPageByQuery(null, sort, pageReq, clazz);
	}

	/**
	 * 按查询条件获取Page
	 * 
	 * @param <T>
	 * 
	 * @param query 查询
	 * @param page  分页
	 * @param clazz 类
	 * @return Page 分页
	 */
	public <T> PageResp<T> findPageByQuery(ConditionWrapper conditionWrapper, PageReq pageReq, Class<T> clazz) {
		return findPageByQuery(conditionWrapper, null, pageReq, clazz);
	}

	/**
	 * 按查询条件获取Page
	 * 
	 * @param query 查询
	 * @param page  分页
	 * @param clazz 类
	 * @return Page 分页
	 */
	public PageResp<?> findPageByQuery(PageReq pageReq, Class<?> clazz) {
		return findPageByQuery(null, null, pageReq, clazz);
	}

	/**
	 * 根据id查找
	 * 
	 * @param id    id
	 * @param clazz 类
	 * @return T 对象
	 */
	public <T> T findById(String id, Class<T> clazz) {
		if (StrUtil.isEmpty(id)) {
			return null;
		}

		SimpleJpaRepository simpleJpaRepository = new SimpleJpaRepository(clazz, entityManager);
		Optional optional = simpleJpaRepository.findById(id);
		if (optional.isEmpty()) {
			return null;
		} else {
			return (T) optional.get();
		}

	}

	/**
	 * 根据条件查找单个
	 * 
	 * @param query 查询
	 * @param clazz 类
	 * @return T 对象
	 */
	public <T> T findOneByQuery(ConditionWrapper conditionWrapper, Sort sort, Class<T> clazz) {
		SimpleJpaRepository simpleJpaRepository = new SimpleJpaRepository(clazz, entityManager);

		Specification specification = new Specification() {
			@Override
			public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {
				if (conditionWrapper != null && conditionWrapper.notEmpty()) {
					Predicate predicate = conditionWrapper.toPredicates(criteriaBuilder, root);
					query.where(predicate);
				}

				if (sort != null && !sort.isEmpty()) {
					query.orderBy(sort.toList());
				}

				return query.getGroupRestriction();
			}
		};

		Optional optional = simpleJpaRepository.findOne(specification);
		if (optional.isEmpty()) {
			return null;
		} else {
			return (T) optional.get();
		}

	}

	/**
	 * 根据条件查找单个
	 * 
	 * @param query 查询
	 * @param clazz 类
	 * @return T 对象
	 */
	public <T> T findOneByQuery(Sort sort, Class<T> clazz) {
		return findOneByQuery(null, sort, clazz);
	}

	/**
	 * 根据条件查找单个
	 * 
	 * @param <T>       类型
	 * @param condition
	 * @param clazz     类
	 * @return T 对象
	 */
	public <T> T findOneByQuery(ConditionWrapper conditionWrapper, Class<T> clazz) {
		return findOneByQuery(conditionWrapper, null, clazz);

	}

	/**
	 * 根据条件查找List
	 * 
	 * @param <T>   类型
	 * @param query 查询
	 * @param clazz 类
	 * @return List 列表
	 */
	public <T> List<T> findListByQuery(ConditionWrapper conditionWrapper, Sort sort, Class<T> clazz) {
		SimpleJpaRepository simpleJpaRepository = new SimpleJpaRepository(clazz, entityManager);

		Specification specification = new Specification() {
			@Override
			public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {
				if (conditionWrapper != null && conditionWrapper.notEmpty()) {
					Predicate predicate = conditionWrapper.toPredicates(criteriaBuilder, root);
					query.where(predicate);
				}
				if (sort != null && !sort.isEmpty()) {
					query.orderBy(sort.toList());
				}

				return query.getGroupRestriction();
			}
		};

		return simpleJpaRepository.findAll(specification);
	}

	/**
	 * 根据条件查找List
	 * 
	 * @param <T>       类型
	 * @param condition 查询
	 * @param clazz     类
	 * @return List 列表
	 */
	public <T> List<T> findListByQuery(ConditionWrapper conditionWrapper, Class<T> clazz) {
		return (List<T>) findListByQuery(conditionWrapper, null, clazz);
	}

	/**
	 * 根据条件查找List
	 * 
	 * @param <T>       类型
	 * @param condition 查询
	 * @param clazz     类
	 * @return List 列表
	 */
	public <T> List<T> findListByQuery(Sort sort, Class<T> clazz) {
		return (List<T>) findListByQuery(null, sort, clazz);
	}

	/**
	 * 根据条件查找某个属性
	 * 
	 * @param <T>           类型
	 * @param query         查询
	 * @param clazz         类
	 * @param property      属性
	 * @param propertyClass 属性类
	 * @return List 列表
	 */
	public <T> List<T> findPropertiesByQuery(ConditionWrapper conditionWrapper, Class<?> clazz, String property, Class<T> propertyClass) {
		List<?> list = findListByQuery(conditionWrapper, clazz);
		List<T> propertyList = extractProperty(list, property, propertyClass);

		return propertyList;
	}

	/**
	 * 根据条件查找某个属性
	 * 
	 * @param <T>           类型
	 * @param query         查询
	 * @param clazz         类
	 * @param property      属性
	 * @param propertyClass 属性类
	 * @return List 列表
	 */
	public <T, R> List<T> findPropertiesByQuery(ConditionWrapper conditionWrapper, Class<?> clazz, SerializableFunction<T, R> property, Class<T> propertyClass) {
		return findPropertiesByQuery(conditionWrapper, clazz, ReflectionUtil.getFieldName(property), propertyClass);
	}

	/**
	 * 根据条件查找某个属性
	 * 
	 * @param <T>       类型
	 * @param condition 查询
	 * @param clazz     类
	 * @param property  属性
	 * @return List 列表
	 */
	public List<String> findPropertiesByQuery(ConditionWrapper conditionWrapper, Class<?> clazz, String property) {
		return findPropertiesByQuery(conditionWrapper, clazz, property, String.class);
	}

	/**
	 * 根据条件查找某个属性
	 * 
	 * @param <T>       类型
	 * @param condition 查询
	 * @param clazz     类
	 * @param property  属性
	 * @return List 列表
	 */
	public <T, R> List<String> findPropertiesByQuery(ConditionWrapper conditionWrapper, Class<?> clazz, SerializableFunction<T, R> property) {
		return findPropertiesByQuery(conditionWrapper, clazz, ReflectionUtil.getFieldName(property), String.class);
	}

	/**
	 * 根据id查找某个属性
	 * 
	 * @param <T>       类型
	 * @param condition 查询
	 * @param clazz     类
	 * @param property  属性
	 * @return List 列表
	 */
	public List<String> findPropertiesByIds(Collection<String> ids, Class<?> clazz, String property) {
		if (ids == null || ids.size() == 0) {
			return new ArrayList<String>();
		}

		ConditionAndWrapper ConditionAndWrapper = new ConditionAndWrapper();
		ConditionAndWrapper.in(getPrimalKey(clazz), ids);

		return findPropertiesByQuery(ConditionAndWrapper, clazz, property, String.class);
	}

	/**
	 * 根据id查找某个属性
	 * 
	 * @param <T>       类型
	 * @param condition 查询
	 * @param clazz     类
	 * @param property  属性
	 * @return List 列表
	 */
	public <T, R> List<String> findPropertiesByIds(Collection<String> ids, Class<?> clazz, SerializableFunction<T, R> property) {
		return findPropertiesByIds(ids, clazz, ReflectionUtil.getFieldName(property));
	}

	/**
	 * 根据id查找某个属性
	 * 
	 * @param <T>       类型
	 * @param condition 查询
	 * @param clazz     类
	 * @param property  属性
	 * @return List 列表
	 */
	public List<String> findPropertiesByIds(String[] ids, Class<?> clazz, String property) {
		return findPropertiesByIds(Arrays.asList(ids), clazz, property);
	}

	/**
	 * 根据id查找某个属性
	 * 
	 * @param <T>       类型
	 * @param condition 查询
	 * @param clazz     类
	 * @param property  属性
	 * @return List 列表
	 */
	public <T, R> List<String> findPropertiesByIds(String[] ids, Class<?> clazz, SerializableFunction<T, R> property) {
		return findPropertiesByIds(Arrays.asList(ids), clazz, ReflectionUtil.getFieldName(property));
	}

	/**
	 * 根据条件查找id
	 * 
	 * @param query 查询
	 * @param clazz 类
	 * @return List 列表
	 */
	public List<String> findIdsByQuery(ConditionWrapper conditionWrapper, Class<?> clazz) {

		return findPropertiesByQuery(conditionWrapper, clazz, getPrimalKey(clazz));
	}

	/**
	 * 根据id集合查找
	 * 
	 * @param List  ids id集合
	 * @param clazz 类
	 * @return List 列表
	 */
	public <T> List<T> findListByIds(Collection<String> ids, Class<T> clazz) {
		return findListByIds(ids, null, clazz);
	}

	/**
	 * 根据id集合查找
	 * 
	 * @param List  ids id集合
	 * @param clazz 类
	 * @return List 列表
	 */
	public <T> List<T> findListByIds(String[] ids, Class<T> clazz) {
		return findListByIds(Arrays.asList(ids), null, clazz);
	}

	/**
	 * 根据id集合查找
	 * 
	 * @param List  ids id集合
	 * @param clazz 类
	 * @return List 列表
	 */
	public <T> List<T> findListByIds(Collection<String> ids, Sort sort, Class<T> clazz) {
		if (ids == null || ids.size() == 0) {
			return new ArrayList<T>();
		}

		ConditionAndWrapper ConditionAndWrapper = new ConditionAndWrapper();
		ConditionAndWrapper.in(getPrimalKey(clazz), ids);

		return findListByQuery(ConditionAndWrapper, sort, clazz);
	}

	/**
	 * 根据id集合查找
	 * 
	 * @param List  ids id集合
	 * @param clazz 类
	 * @return List 列表
	 */
	public <T> List<T> findListByIds(String[] ids, Sort sort, Class<T> clazz) {
		return findListByIds(Arrays.asList(ids), sort, clazz);
	}

	/**
	 * 查询全部
	 * 
	 * @param <T>   类型
	 * @param clazz 类
	 * @return List 列表
	 */
	public <T> List<T> findAll(Class<T> clazz) {
		return findAll(null, clazz);
	}

	/**
	 * 查询全部
	 * 
	 * @param <T>   类型
	 * @param clazz 类
	 * @return List 列表
	 */
	public <T> List<T> findAll(Sort sort, Class<T> clazz) {
		return findListByQuery(null, sort, clazz);
	}

	/**
	 * 查找全部的id
	 * 
	 * @param clazz 类
	 * @return List 列表
	 */
	public List<String> findAllIds(Class<?> clazz) {
		return findIdsByQuery(null, clazz);
	}

	/**
	 * 查找数量
	 * 
	 * @param condition 查询
	 * @param clazz     类
	 * @return Long 数量
	 */
	public Long findCountByQuery(ConditionWrapper conditionWrapper, Class<?> clazz) {
		SimpleJpaRepository simpleJpaRepository = new SimpleJpaRepository(clazz, entityManager);

		Specification specification = new Specification() {
			@Override
			public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {
				if (conditionWrapper != null && conditionWrapper.notEmpty()) {
					Predicate predicate = conditionWrapper.toPredicates(criteriaBuilder, root);
					query.where(predicate);
				}

				return query.getGroupRestriction();
			}
		};

		return simpleJpaRepository.count(specification);

	}

	/**
	 * 查找全部数量
	 * 
	 * @param clazz 类
	 * @return Long 数量
	 */
	public Long findAllCount(Class<?> clazz) {
		return findCountByQuery(null, clazz);
	}

	/**
	 * 获取list中对象某个属性,组成新的list
	 * 
	 * @param list     列表
	 * @param clazz    类
	 * @param property 属性
	 * @return List<T> 列表
	 */
	private <T> List<T> extractProperty(List<?> list, String property, Class<T> clazz) {
		Set<T> rs = new HashSet<T>();
		for (Object object : list) {
			Object value = ReflectUtil.getFieldValue(object, property);
			if (value != null && value.getClass().equals(clazz)) {
				rs.add((T) value);
			}
		}

		return new ArrayList<T>(rs);
	}

	/**
	 * Map转Bean
	 * 
	 * @param <T>
	 * @param queryForList
	 * @param clazz
	 * @return
	 */
	private <T> List<T> buildObjects(List<Map<String, Object>> queryForList, Class<T> clazz) {
		List<T> list = new ArrayList<T>();
		try {
			Field[] fields = ReflectUtil.getFields(clazz);

			for (Map<String, Object> map : queryForList) {
				Object obj = clazz.getDeclaredConstructor().newInstance();

				for (Map.Entry<String, Object> entry : map.entrySet()) {
					String mapKey = entry.getKey();
					Object mapValue = entry.getValue();

					for (Field field : fields) {
						if (StrUtil.toUnderlineCase(field.getName()).equals(mapKey)) {
							ReflectUtil.setFieldValue(obj, field.getName(), mapValue);
							break;
						}
					}

				}

				list.add((T) obj);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}

}
